package org.nhindirect.stagent;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Collection;

public class EntitySerializer 
{
    public static final EntitySerializer Default = new EntitySerializer();
    
    public EntitySerializer()
    {
    }
    
    public void serialize(MimeEntity entity, OutputStream stream)
    {
    	Writer writer = new OutputStreamWriter(stream, Charset.forName("ASCII"));

        this.serialize(entity, writer);
    }
    
    public void serialize(MimeEntity entity, Writer writer)
    {
        if (entity == null)
        {
            throw new IllegalArgumentException();
        }
        
        EntityWriter entityWriter = new EntityWriter(writer);
        if (entity.hasHeaders())
        {
            entityWriter.write(entity.getHeaders());
            entityWriter.writeCRLF();
        }
        if (entity.hasBody())
        {
            entityWriter.write(entity.getBody());
            if (entity instanceof Message)
            {
                entityWriter.writeCRLF();
            }            
        }
        
        entityWriter.flush();
    }

    public void serialize(MimeEntity entity, EntityWriter entityWriter)
    {
        if (entity == null || entityWriter == null)
        {
            throw new IllegalArgumentException();
        }

        if (entity.hasHeaders())
        {
            entityWriter.write(entity.getHeaders());
            entityWriter.writeCRLF();
        }
        if (entity.hasBody())
        {
            entityWriter.write(entity.getBody());
            if (entity instanceof Message)
            {
                entityWriter.writeCRLF();
            }                
        }
        
        entityWriter.flush();
    }
    
    public String serialize(MimeEntity entity)
    {
    	String retVal = "";
    	
        byte[] asciiBytes = this.serializeToBytes(entity);
        try
        {
        	retVal = new String(asciiBytes, "ASCII");
        }
        catch (UnsupportedEncodingException e){}
        
        return retVal;
    }
    
    public byte[] serializeToBytes(MimeEntity entity)
    {
    	ByteArrayOutputStream bstream = new ByteArrayOutputStream();

    	OutputStream stream = new BufferedOutputStream(bstream);
    	
        this.serialize(entity, stream);
        return bstream.toByteArray();
    }

    public void serialize(Collection<MimeEntity> entities, String boundary, Writer writer)
    {
        if (entities == null)
        {
            throw new IllegalArgumentException();
        }
        
        EntityWriter entityWriter = new EntityWriter(writer);
        for (MimeEntity entity : entities)
        {
            entityWriter.writeMimeBoundary(boundary, false);
            this.serialize(entity, entityWriter);
        }
        entityWriter.writeMimeBoundary(boundary, true);
        
        entityWriter.flush();
    }

    public String serialize(Collection<MimeEntity> entities, String boundary)
    {
    	String retVal = "";
    	
        byte[] asciiBytes = this.serializeToBytes(entities, boundary);
        try
        {
        	retVal =  new String(asciiBytes, "ASCII");
        }
        catch (UnsupportedEncodingException e){}
        
        return retVal;
    }

    public void serialize(Collection<MimeEntity> entities, String boundary, OutputStream stream)
    {
    	Writer writer = new OutputStreamWriter(stream, Charset.forName("ASCII"));
        this.serialize(entities, boundary, writer);
    }

    public byte[] serializeToBytes(Collection<MimeEntity> entities, String boundary)
    {        
    	ByteArrayOutputStream bstream = new ByteArrayOutputStream();

    	OutputStream stream = new BufferedOutputStream(bstream);
    	
        this.serialize(entities, boundary, stream);
        return bstream.toByteArray();        
    }

    public MimeEntity deserialize(InputStream stream)
    {
        if (stream == null)
        {
            throw new IllegalArgumentException();
        }

        Reader reader = new InputStreamReader(stream);
        

        return this.deserialize(reader);
    }
    
    public MimeEntity deserialize(Reader reader)
    {
        if (reader == null)
        {
            throw new IllegalArgumentException();
        }
        
        StringBuilder builder = new StringBuilder();
        char[] buffer = new char[1024]; 
        

        int numRead = 0;
        try
        {
	        while ((numRead = reader.read(buffer)) > -1)
			{
	        	builder.append(buffer, 0, numRead);
			}
        }
        catch (IOException e){}
        
        return this.deserialize(builder.toString());
    }

    public MimeEntity deserialize(String messageText)
    {
        if (messageText == null  || messageText.length() == 0)
        {
            throw new IllegalArgumentException();
        }
        
        return this.deserialize(new StringSegment(messageText));
    }

    public MimeEntity deserialize(StringSegment messageText)
    {
        return EntityParser.read(messageText);
    }
    
    public MimeEntity deserialize(byte[] messageBytes)
    {
        if (messageBytes == null || messageBytes.length == 0)
        {
            throw new IllegalArgumentException();
        }
        
        InputStream stream = new ByteArrayInputStream(messageBytes);
        
        return this.deserialize(stream);
    }
}
